/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * GSelect.java
 *
 * Created on Mar 30, 2011, 9:05:23 PM
 */

package edu.pdx.cs.guavalib;

import edu.pdx.cs.guavadata.AppData;
import edu.pdx.cs.guavadata.GSeed;
import edu.pdx.cs.guavadata.Guava;
import edu.pdx.cs.guavadata.domain.AnnotatedGuid;
import edu.pdx.cs.guavadata.domain.Domain;
import edu.pdx.cs.guavadata.subclass.ControlType;
import edu.pdx.cs.guavadata.subclass.DataColumn;
import edu.pdx.cs.guavadata.subclass.DataTable;
import edu.pdx.cs.guavadata.subclass.GuavaForm;
import edu.pdx.cs.guavadata.subclass.GuavaLaunchBase;
import edu.pdx.cs.guavadata.subclass.LaunchType;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;

/**
 *
 * @author VuTran
 */
public class GSelect extends javax.swing.JPanel implements Guava, GuavaLaunchBase {

    /** Creates new form GSelect */
    public GSelect() {
        initComponents();
        columnsFound = new ArrayList<String>();
        cmbItems.addItemListener(new ItemListener() {

            public void itemStateChanged(ItemEvent e) {
                cmbItemChanged(e);
            }
        });
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        cmbItems = new javax.swing.JComboBox();
        btnNew = new javax.swing.JButton();
        btnEdit = new javax.swing.JButton();
        btnDelete = new javax.swing.JButton();
        lblTitle = new javax.swing.JLabel();

        btnNew.setText("New");
        btnNew.setName("btnNew"); // NOI18N
        btnNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNewActionPerformed(evt);
            }
        });

        btnEdit.setText("Edit");
        btnEdit.setName("btnEdit"); // NOI18N
        btnEdit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnEditActionPerformed(evt);
            }
        });

        btnDelete.setText("Delete");
        btnDelete.setName("btnDelete"); // NOI18N
        btnDelete.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDeleteActionPerformed(evt);
            }
        });

        lblTitle.setText("jLabel1");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(cmbItems, 0, 179, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(btnNew)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnEdit)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnDelete))
                    .addComponent(lblTitle))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(lblTitle, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(cmbItems, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(6, 6, 6)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnNew)
                    .addComponent(btnEdit)
                    .addComponent(btnDelete))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void btnNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewActionPerformed
        UUID gtemp = UUID.randomUUID();
        this.prepareStackFrame();
        this.launchForm(gtemp, null, true);
        buildList();
        setObject(gtemp);
    }//GEN-LAST:event_btnNewActionPerformed

    private void btnEditActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEditActionPerformed
        if (cmbItems.getItemCount() <= 0) return;
        if (cmbItems.getSelectedIndex() < 0) return;
        UUID gtemp = ((AnnotatedGuid) cmbItems.getSelectedItem()).getObject();
        launchForm(gtemp, null, false);
        buildList();
        setObject(gtemp);
    }//GEN-LAST:event_btnEditActionPerformed

    private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteActionPerformed
        if (cmbItems.getItemCount() <= 0) return;
        if (cmbItems.getSelectedIndex() < 0) return;
        UUID toDel = ((AnnotatedGuid) cmbItems.getSelectedItem()).getObject();

        if (JOptionPane.showConfirmDialog(this, "Are you sure that you want to delete" + cmbItems.getSelectedItem().toString() + "?",
                "Confirm Delete", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.NO_OPTION)
            return;

        AppData.deleteRow(getGComponents().get(0).getGName(), toDel);
        buildList();
    }//GEN-LAST:event_btnDeleteActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnDelete;
    private javax.swing.JButton btnEdit;
    private javax.swing.JButton btnNew;
    private javax.swing.JComboBox cmbItems;
    private javax.swing.JLabel lblTitle;
    // End of variables declaration//GEN-END:variables

    String gname;
    Class s;
    String gview;
    DataTable dv;
    String strLaunchFile;
    List<String> columnsFound;
    String firstColumn;
    String gn;

    public void cmbItemChanged(ItemEvent e) {
        JComboBox cb = (JComboBox) e.getSource();

        if (e.getStateChange() == ItemEvent.SELECTED) {
            
        }
    }

    public LaunchType getLType() {
        return LaunchType.Multi;
    }

    public ControlType getCType() {
        return ControlType.None;
    }

    public String getGText() {
        return lblTitle.getText();
    }

    public void setGText(String value) {
        lblTitle.setText(value);
    }

    public String getGName() {
        if (gname == null)
            return this.getName();
        return gname;
    }

    public void setGName(String GName) {
        gname = GName;
    }

    public Point getGLocation() {
        return this.getLocation();
    }

    public Dimension getGSize() {
        return this.getSize();
    }

    public List<Guava> getGComponents() {
        try {
            List<Guava> lg = new ArrayList<Guava>();
            if (getLaunchType() == null) {
                return lg;
            }
            Constructor ci = s.getConstructor(new Class[]{});
            Object o = ci.newInstance(new Object[] { });
            lg.add((Guava) o);

            return lg;
        } catch (Exception ex) {
            System.err.println("ERROR: " + ex.toString());
        }
        return null;
    }

    public String getGLaunchType() {
        return strLaunchFile;
    }

    public void setGLaunchType(String launchType) {
        this.strLaunchFile = launchType;
    }

    public Class getLaunch() {
        return s;
    }

    public void setLaunch(Class s) {
        this.s = s;
    }

    public Class getLaunchType() {
        if ((s == null) && strLaunchFile.length() > 0) {
            try {
                s = Class.forName(strLaunchFile);
            } catch (ClassNotFoundException ex) {
                System.err.println("ERROR: " + ex.toString());
            }
        }
        return s;
    }

    public String getView() {
        return gview;
    }

    public void setView(String view) {
        gview = view;
    }

    public void gBind(String table, int i) {
        try {
            // Find the name of the launched table
            Constructor ci = getLaunchType().getConstructor(new Class[]{});
            Object o = ci.newInstance(new Object[] {});
            Field p = s.getField("GName");
            Method mName = s.getMethod("getGName", new Class[] {});
            gn = (String) mName.invoke(o, new Object[] {});

            // Retrieve the ID from the parent form
            UUID gid = ((GuavaForm) this.getTopLevelAncestor()).getID();

            // Fetch the appropriate rows
            AppData.fetchRowsByFK(gn, gid);
            DataTable targetTable = AppData.ds.getTable(gn);

            // Accept loading of rows into memory

            // parse view attributes
            columnsFound.clear();
            for (DataColumn dc : targetTable.columns) {
                String toFind = "<" + dc.getName() + ">";
                if (gview != null) {
                    if (gview.contains(toFind)) {
                        columnsFound.add(dc.getName());
                        if (firstColumn == null) {
                            firstColumn = dc.getName();
                        }  else if (gview.indexOf(dc.getName()) < gview.indexOf(firstColumn)) {
                            firstColumn = dc.getName();
                        }
                    }
                }
            }

            // Create a view of the destination table that only has the current ID's
            if (!(gid.equals(UUID.nameUUIDFromBytes("000".getBytes())))) {
                //dv = new DataView(targetTable, "fk='" + gid.ToString() + "'", firstColumn, DataViewRowState.CurrentRows);
                dv = targetTable.getDataView("fk", gid.toString());
            } else {
                dv = AppData.ds.getTable(gn);
            }
            //else dv = new DataView(AppData.ds.Tables[gn]);

            buildList();
            
        } catch (Exception ex) {
            System.err.println("ERROR: " + ex.toString());
        }

        return;
    }

    public void gBindFromDatabase(String table, int i) {
        try {
            // Find the name of the launched table
            Constructor ci = getLaunchType().getConstructor(new Class[]{});
            Object o = ci.newInstance(new Object[] {});
            Field p = s.getField("GName");
            Method mName = s.getMethod("getGName", new Class[] {});
            gn = (String) mName.invoke(o, new Object[] {});

            // Retrieve the ID from the parent form
            UUID gid = ((GuavaForm) this.getTopLevelAncestor()).getID();

            // Fetch the appropriate rows
            AppData.fetchRowsByFK(gn, gid);
            DataTable targetTable = AppData.ds.getTable(gn);

            // Accept loading of rows into memory

            // parse view attributes
            columnsFound.clear();
            for (DataColumn dc : targetTable.columns) {
                String toFind = "<" + dc.getName() + ">";
                if (gview != null) {
                    if (gview.contains(toFind)) {
                        columnsFound.add(dc.getName());
                        if (firstColumn == null) {
                            firstColumn = dc.getName();
                        }  else if (gview.indexOf(dc.getName()) < gview.indexOf(firstColumn)) {
                            firstColumn = dc.getName();
                        }
                    }
                }
            }

            // Create a view of the destination table that only has the current ID's
            if (!(gid.equals(UUID.nameUUIDFromBytes("000".getBytes())))) {
                //dv = new DataView(targetTable, "fk='" + gid.ToString() + "'", firstColumn, DataViewRowState.CurrentRows);
                dv = targetTable.getDataView("fk", gid.toString());
            } else {
                dv = AppData.ds.getTable(gn);
            }
            //else dv = new DataView(AppData.ds.Tables[gn]);

            buildList();

        } catch (Exception ex) {
            System.err.println("ERROR: " + ex.toString());
        }

        return;
    }

    public void buildList() {
        // build the list of combo box items
        List<Object> lo = new ArrayList<Object>();
        if (dv.rows != null) {
            for (Map<String, Object> dr : dv.rows) {
                String temp = gview;
                for (String s : columnsFound) {
                    temp = temp.replace("<" + s + ">", dr.get(s).toString());
                }
                lo.add(new AnnotatedGuid(UUID.fromString(dr.get("id").toString()), temp, dr));
            }
        }

        // restore objects and highlighted item
        AnnotatedGuid ag = (AnnotatedGuid) cmbItems.getSelectedItem();
        cmbItems.removeAllItems();
        for (Object o : lo) {
            cmbItems.addItem(o);
        }
        refreshCmb();
        if (ag != null) {
            setObject(ag.getObject());
        }
    }
    
    public String getGDefault() {
        return null;
    }

    public String getGToolTip() {
        return this.getToolTipText();
    }

    public Domain getGDomain() {
        return null;
    }

    public Guava get(String s) {
        for (Guava g : this.getGComponents()) {
            if (g.getGName().equals(s)) {
                return g;
            }
        }
        return null;
    }

    public void setObject(UUID id) {
        for (int i = 0; i < cmbItems.getItemCount(); i++) {
            Object o = cmbItems.getItemAt(i);
            AnnotatedGuid ag = (AnnotatedGuid) o;
            if (ag.getObject().equals(id)) {
                cmbItems.setSelectedItem(o);
                return;
            }
        }

        this.cmbItems.setSelectedIndex(-1);
        refreshCmb();
    }

    public void refreshCmb() {
        cmbItems.updateUI();
        cmbItems.repaint();
        cmbItems.revalidate();
    }
    public void prepareStackFrame() {
        return;
    }

    public int launchForm(UUID gid, String form, boolean bNew) {
        int d = 0; // dialog result

        if (getLaunchType() == null)
            return JOptionPane.CANCEL_OPTION;
        try {
            Component p = this.getTopLevelAncestor();
            if (p instanceof GJFrame) {
                Constructor cons = s.getConstructor(new Class[]{UUID.class, UUID.class,
                        boolean.class, GSeed.class, java.awt.Frame.class, boolean.class});
                GJDialog o = (GJDialog) cons.newInstance(new Object[] { gid, ((GuavaForm) this.getTopLevelAncestor()).getID(),
                        bNew, ((GuavaForm) p).gs, p, true });

                o.setVisible(true);
                d = o.dialogResult;
            } else {
                Constructor cons = s.getConstructor(new Class[]{UUID.class, UUID.class,
                        boolean.class, GSeed.class, java.awt.Dialog.class, boolean.class});
                GJDialog o = (GJDialog) cons.newInstance(new Object[] { gid, ((GuavaForm) this.getTopLevelAncestor()).getID(),
                        bNew, ((GuavaForm) p).gs, p, true });

                o.setVisible(true);
                d = o.dialogResult;
            }

            // when done, refresh the item
            refreshCmb();
            return d;
        } catch (Exception e) {
        }

        return 0;
    }

}
